package me.ycy.android.couchbase.server

import scala.reflect.{ BooleanBeanProperty, BeanProperty }
import java.util.Date
import java.text.SimpleDateFormat

import android.util.Log
import android.content.{ Context, Intent }
import android.widget.{ BaseAdapter, TextView }
import android.view.{ ViewGroup, View, LayoutInflater }
import android.preference.PreferenceManager
import android.app.Activity
import android.os.Bundle
import android.widget._

import java.util.HashMap
import java.util.concurrent.LinkedBlockingQueue

import org.codehaus.jackson.JsonFactory
import org.codehaus.jackson.map.ObjectMapper
import org.codehaus.jackson.map.`type`._

import scala.collection.mutable.{ Map => mMap }
import java.util.{ Map => jMap }

import replication._
import ReplicatorDb.{ withReplicators, modifyReplicators }

import org.ektorp._

/*
 ---- UI for each row ----
 Replication id(large bold)
 source(bold) source
 target(bold) target
 status lastSeq [create_target] [continuous] timestamp(righ align)

touch each row, trigger replication if not in trigger status
long touch each row to edit replication
*/

class ReplicationAdapter(val ctx: Context) extends BaseAdapter() {
  val Tag = "CouchbaseServer"
  val df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
  val inflater: LayoutInflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE).
    asInstanceOf[LayoutInflater]

  def getItem(pos: Int): Replicator = {
    ReplicatorDb.getReplicator(pos)
  }

  def getItemId(pos: Int): Long = {
    val obj = getItem(pos)
    if (obj != null) obj.id.hashCode else 0
  }

  def getCount = withReplicators(_.size)

  def getView(pos: Int, convertView: View, p: ViewGroup): View = {
    val v = if (convertView == null) {
      inflater.inflate(R.layout.replication_row, p, false);
    }
    else {
      convertView
    }

    val r = getItem(pos)
    def setText(id: Int, text: String) =
        v.findViewById(id).asInstanceOf[TextView].setText(text)
    try {
      setText(R.id.repId, r.id)
      setText(R.id.repSource, r.source)
      setText(R.id.repTarget, r.target)
      setText(R.id.repStatusLeft, r.replicationState)
      var s = df.format(r.replicationStateTime)
      if (r.continuous) s = "C " + s
      if (r.createTarget) s = "T " + s
      setText(R.id.repStatusRight, s)
      setText(R.id.repStartedOn,
              if (r.startedOn.getTime == 0) "-" else df.format(r.startedOn))
      setText(R.id.repUpdatedOn,
              if (r.updatedOn.getTime == 0) "-" else df.format(r.updatedOn))
      setText(R.id.repStatus, r.status)
    }
    catch {
      case e => e.printStackTrace
    }
    v
  }
}

object ReplicationEdit {
  def add(a: Activity, req: Int) = {
    val i = new Intent(a, classOf[ReplicationEdit])
    a.startActivityForResult(i, req)
  }

  def edit(a: Activity, req: Int, id: String) = {
    val i = new Intent(a, classOf[ReplicationEdit])
    i.putExtra("id", id)
    a.startActivityForResult(i, req)
  }
}

class ReplicationEdit extends Activity {
  // this should not be null
  var rep: Replicator = new Replicator

  def w[T](id: Int): T = findViewById(id).asInstanceOf[T]

  lazy val reId = w[EditText](R.id.repEditId)
  lazy val reSource = w[EditText](R.id.repEditSource)
  lazy val reTarget = w[EditText](R.id.repEditTarget)
  lazy val reContinuous = w[CheckBox](R.id.repEditContinuous)
  lazy val reCreateTarget = w[CheckBox](R.id.repEditCreateTarget)
  lazy val reMaxRetryInterval = w[EditText](R.id.repEditMaxRetryInterval)

  // fill data from config
  def setData(k: String) = {
    val r = withReplicators(_.apply(k.hashCode))

    reId.setText(r.id)
    reSource.setText(r.source)
    reTarget.setText(r.target)
    reContinuous.setChecked(r.continuous)
    reCreateTarget.setChecked(r.createTarget)
    reMaxRetryInterval.setText(r.maxRetryInterval.toString)
  }

  // get data and check
  def getData(): Option[Replicator] = {
    val r = new Replicator

    def ce(tv: TextView): Boolean = {
      if (tv.getText.length == 0) {
        tv.requestFocus()
        return true
      }
      false
    }
    List(reId, reSource, reTarget, reMaxRetryInterval).foreach { x => {
      if (ce(x)) return None
    }}

    try {
      r.maxRetryInterval = reMaxRetryInterval.getText.toString.toInt
    }
    catch {
      case _ => return None
    }

    // TODO, check more for source & target
    r.id = reId.asInstanceOf[TextView].getText.toString
    r.source = reSource.asInstanceOf[TextView].getText.toString
    r.target = reTarget.asInstanceOf[TextView].getText.toString
    r.continuous = reContinuous.isChecked
    r.createTarget = reCreateTarget.isChecked

    new Some(r)
  }

  def buttonOnClick(id: Int)(func: View => Unit) = {
    val cl = new View.OnClickListener {
      def onClick(v: View) = func(v)
    }
    (findViewById(id).asInstanceOf[Button]).setOnClickListener(cl)
  }

  def handleEvent: Unit = {
    buttonOnClick(R.id.repEditOk) { v => {
      getData() match {
        case Some(r) => {
          try {
            // delete old one
            if ((rep.id != r.id) && (rep.id != null)) {
              ReplicatorDb.delete(rep)
            }
            ReplicatorDb.save(r)
          }
          catch {
            case e: DbAccessException => {
              Toast.makeText(getApplicationContext(), "Error: " + e.getMessage,
                             Toast.LENGTH_LONG).show()
            }
            case e => {
              Toast.makeText(getApplicationContext(), "Error: " + e.getMessage,
                             Toast.LENGTH_LONG).show()
            }
          }

          finish()
        }
        case _ => {
        }
      }
    }}

    buttonOnClick(R.id.repEditCancel) { v => {
      setResult(Activity.RESULT_CANCELED)
      finish()
    }}
  }

  override def onCreate(savedInstanceState: Bundle) : Unit = {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.replication_edit)
    handleEvent

    // fill intent
    val i = getIntent()
    val k = i.getStringExtra("id")
    if (k != null) {
      setData(k)
      rep = withReplicators(_.apply(k.hashCode))
    }
    else {
      rep = new Replicator
    }
  }
}
